import { create } from 'zustand';
import apiService from '../lib/api'; // Corrected import path

interface ProviderDetails {
  is_configured: boolean;
  metadata: {
    config_keys: Array<{
      name: string;
      oauth_flow: boolean;
      required: boolean;
      secret: boolean;
      default?: string | null;
    }>;
    default_model: string;
    description: string;
    display_name: string;
    known_models: Array<{
      context_limit: number;
      currency?: string | null;
      input_token_cost?: number | null;
      name: string;
      output_token_cost?: number | null;
      supports_cache_control?: boolean | null;
    }>;
    model_doc_link: string;
    name: string;
  };
  name: string;
}

interface ProviderConfig {
  [key: string]: string; // Stores key-value pairs for provider configuration
}

interface ProviderState {
  availableProviders: ProviderDetails[];
  configuredProviders: Record<string, ProviderConfig>;
  selectedProvider: string | null;
  loading: boolean;
  error: string | null;
  
  loadProviders: () => Promise<void>;
  upsertProviderConfig: (providerName: string, key: string, value: string, isSecret: boolean) => Promise<void>;
  readProviderConfig: (providerName: string, key: string, isSecret: boolean) => Promise<string | null>;
  setSelectedProvider: (providerName: string | null) => void;
  
  // Helper to get a specific provider's config by name
  getProviderConfig: (providerName: string) => ProviderConfig | undefined;
  // Helper to check if a provider is fully configured based on its required_config_keys
  isProviderFullyConfigured: (providerName: string) => boolean;
}

export const useProviderStore = create<ProviderState>((set, get) => ({
  availableProviders: [],
  configuredProviders: {},
  selectedProvider: null,
  loading: false,
  error: null,

  loadProviders: async () => {
    set({ loading: true, error: null });
    try {
      const data = await apiService.getProviders();
      set({ availableProviders: data.providers, loading: false });
    } catch (error: any) {
      set({ error: error.message || 'Failed to load providers', loading: false });
      console.error('Failed to load providers:', error);
    }
  },

  upsertProviderConfig: async (providerName, key, value, isSecret) => {
    set({ loading: true, error: null });
    try {
      await apiService.upsertConfig({ key, value, is_secret: isSecret });
      // Optimistically update configuredProviders
      set(state => ({
        configuredProviders: {
          ...state.configuredProviders,
          [providerName]: {
            ...(state.configuredProviders[providerName] || {}),
            [key]: value,
          },
        },
        loading: false,
      }));
    } catch (error: any) {
      set({ error: error.message || 'Failed to upsert provider config', loading: false });
      console.error('Failed to upsert provider config:', error);
      throw error; // Re-throw to allow UI to handle specific errors
    }
  },

  readProviderConfig: async (providerName, key, isSecret) => {
    set({ loading: true, error: null });
    try {
      const data = await apiService.readConfig({ key, is_secret: isSecret });
      // Assuming readConfig returns { value: string }
      const value = data.value; // Adjust based on actual API response structure
      set(state => ({
        configuredProviders: {
          ...state.configuredProviders,
          [providerName]: {
            ...(state.configuredProviders[providerName] || {}),
            [key]: value,
          },
        },
        loading: false,
      }));
      return value;
    } catch (error: any) {
      set({ error: error.message || 'Failed to read provider config', loading: false });
      console.error('Failed to read provider config:', error);
      return null;
    }
  },

  setSelectedProvider: (providerName) => {
    set({ selectedProvider: providerName });
  },

  getProviderConfig: (providerName: string) => {
    return get().configuredProviders[providerName];
  },

  isProviderFullyConfigured: (providerName: string) => {
    const state = get();
    const providerDetails = state.availableProviders.find(p => p.name === providerName);
    if (!providerDetails) return false;

    const configured = state.configuredProviders[providerName];
    if (!configured) return false;

    return providerDetails.metadata.config_keys.every(key => {
      if (key.required) {
        return configured[key.name] !== undefined && configured[key.name] !== '';
      }
      return true;
    });
  },
}));
